package org.rc.six;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Wrapper for the inverted tree index.
 * @author dokeeffe
 */
public class Index implements Serializable {

    private static final Logger LOGGER = LoggerFactory.getLogger(Index.class);
    private String stem;
    
    private TreeMap<String, Set<String>> index = new TreeMap<String, Set<String>>();

    /**
     * Constructor passed the stem
     * @param stem
     */
    Index(String stem) {
        this.stem = stem;
    }

    /**
     * @return the stem
     */
    public String getStem() {
        return stem;
    }

    /**
     * @param stem the stem to set
     */
    public void setStem(String stem) {
        this.stem = stem;
    }

    /**
     * Add a document to the inverted tree index for the search term passed
     * @param term 
     * @param doc 
     */
    public void addDocument(String term, Document doc) {
        LOGGER.debug("adding doc for term " + term);
        if(index.get(term)==null) {
            Set<String> docs= new HashSet<String>();
            docs.add(toJson(doc));
            index.put(term, docs);
        } else {
            boolean added = index.get(term).add(toJson(doc));
            if(!added) {
                LOGGER.debug("document already in index");
            }
        }
    }

    /**
     * Returns a collection of json serialized {@link Document}s 
     * from this index that start with the term passed.
     * @param term
     * @return
     */
    public Set<String> lookupTermRadix(String term) {
        Set<String> result = new HashSet<String>();
        Collection<Set<String>> sets = this.index.subMap(term,term+"z").values();
        for(Set s : sets) {
            result.addAll(s);
        }
        return result;
    }

    /**
     * Returns a collection of json serialized {@link Document}s
     * from this index that match the term passed.
     * @param term
     * @return
     */
    public Set<String> lookupExactTerm(String term) {
        Set<String> result = this.index.get(term);
        return result;
    }
    /**
     * Searilize to json
     * @param doc
     * @return
     */
    private String toJson(Document doc) {
        Type docType = new TypeToken<Document>() {
        }.getType();
        Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
        String json = gson.toJson(doc, docType);
        return json;
    }



}
